home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / Demos / DuelVoice / dpconnect.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-31  |  44.7 KB  |  1,283 lines

  1. //-----------------------------------------------------------------------------
  2. // File: DPConnect.cpp
  3. //
  4. // Desc: Support file to prompt the user for the DirectPlay connection 
  5. //       and the DirectPlay session they want to join or create. 
  6. //
  7. //       Call DPConnect_StartDirectPlayConnect() to start the series of 
  8. //       dialogs boxes.  At the end the player will be connected to an active
  9. //       DirectPlay session that the user either created or joined.  Or the 
  10. //       function may also return an EXITCODE as defined below in the event
  11. //       of error or user cancel.  
  12. //
  13. // Copyright (c) 1999-2001 Microsoft Corp. All rights reserved.
  14. //-----------------------------------------------------------------------------
  15. #define IDIRECTPLAY2_OR_GREATER
  16. #include <windows.h>
  17. #include <basetsd.h>
  18. #include <dplobby.h>
  19. #include <dplay.h>
  20. #include <stdio.h>
  21. #include "resource.h"
  22.  
  23.  
  24.  
  25.  
  26. //-----------------------------------------------------------------------------
  27. // Defines, and constants
  28. //-----------------------------------------------------------------------------
  29. #define SAFE_DELETE(p)       { if(p) { delete (p);     (p)=NULL; } }
  30. #define SAFE_DELETE_ARRAY(p) { if(p) { delete[] (p);   (p)=NULL; } }
  31. #define SAFE_RELEASE(p)      { if(p) { (p)->Release(); (p)=NULL; } }
  32.  
  33. #define MAX_PLAYER_NAME      14
  34. #define MAX_SESSION_NAME     256
  35.  
  36. struct DPSessionInfo
  37. {
  38.     GUID guidSession;
  39.     TCHAR szSession[MAX_SESSION_NAME];
  40.     DPSessionInfo* pDPSINext;
  41. };
  42.  
  43.  
  44.  
  45.  
  46. //-----------------------------------------------------------------------------
  47. // Global variables
  48. //-----------------------------------------------------------------------------
  49. #define EXITCODE_FORWARD      1  // Dialog success, so go forward
  50. #define EXITCODE_BACKUP       2  // Dialog canceled, show previous dialog
  51. #define EXITCODE_QUIT         3  // Dialog quit, close app
  52. #define EXITCODE_ERROR        4  // Dialog error, terminate app
  53. #define EXITCODE_LOBBYCONNECT 5  // Dialog connected from lobby, connect success
  54.  
  55. extern LPDIRECTPLAY4A       g_pDP;
  56. extern LPDPLCONNECTION      g_pDPLConnection;
  57. extern LPDIRECTPLAYLOBBY3   g_pDPLobby;
  58. extern GUID                 g_AppGUID; 
  59. extern HANDLE               g_hDPMessageEvent;
  60. extern TCHAR                g_strPreferredProvider[MAX_SESSION_NAME];
  61. extern TCHAR                g_strSessionName[MAX_SESSION_NAME];
  62. extern TCHAR                g_strLocalPlayerName[MAX_PLAYER_NAME];
  63. extern DPID                 g_LocalPlayerDPID; 
  64. extern BOOL                 g_bHostPlayer;
  65. extern TCHAR                g_strAppName[256];
  66. extern BOOL                 g_bUseProtocol;
  67. extern BOOL                 g_bAsyncSupported; // Asynchronous sends supported
  68.  
  69. DPSessionInfo               g_DPSIHead;
  70. BOOL                        g_bSearchingForSessions;
  71. BOOL                        g_bWaitForConnectionSettings;
  72.  
  73.  
  74.  
  75.  
  76. //-----------------------------------------------------------------------------
  77. // Function-prototypes
  78. //-----------------------------------------------------------------------------
  79. int             DPConnect_StartDirectPlayConnect( HINSTANCE hInst, BOOL bBackTrack );
  80.  
  81. INT_PTR CALLBACK DPConnect_ConnectionsDlgProc( HWND, UINT, WPARAM, LPARAM );
  82. BOOL FAR PASCAL DPConnect_EnumConnectionsCallback( LPCGUID, VOID*, DWORD, LPCDPNAME, DWORD, VOID* );
  83. HRESULT         DPConnect_ConnectionsDlgFillListBox( HWND hDlg );
  84. HRESULT         DPConnect_ConnectionsDlgOnOK( HWND hDlg );
  85. VOID            DPConnect_ConnectionsDlgCleanup( HWND hDlg );
  86.  
  87. INT_PTR CALLBACK DPConnect_SessionsDlgProc( HWND, UINT, WPARAM, LPARAM );
  88. INT_PTR CALLBACK DPConnect_CreateSessionDlgProc( HWND, UINT, WPARAM, LPARAM );
  89. BOOL FAR PASCAL DPConnect_EnumSessionsCallback( LPCDPSESSIONDESC2, DWORD*, DWORD, VOID* );
  90. VOID            DPConnect_SessionsDlgInitListbox( HWND hDlg );
  91. HRESULT         DPConnect_SessionsDlgShowGames( HWND hDlg );
  92. HRESULT         DPConnect_SessionsDlgJoinGame( HWND hDlg );
  93. HRESULT         DPConnect_SessionsDlgCreateGame( HWND hDlg );
  94. VOID            DPConnect_SessionsDlgCleanup();
  95.  
  96. INT_PTR CALLBACK DPConnect_LobbyWaitDlgProc( HWND, UINT, WPARAM, LPARAM );
  97. HRESULT         DPConnect_CheckForLobbyLaunch( BOOL* pbLaunchedByLobby );
  98. HRESULT         DPConnect_DoLobbyLaunch();
  99. HRESULT         DPConnect_WaitForLobbyLaunch( HWND hParentDlg );
  100. HRESULT         DPConnect_GetLobbyConnectionSettingsMessage();
  101.  
  102.  
  103.  
  104.  
  105. //-----------------------------------------------------------------------------
  106. // Name: DPConnect_StartDirectPlayConnect()
  107. // Desc: Prompts the user for the DirectPlay connection and the DirectPlay 
  108. //       session they want to join or create.  This function returns one
  109. //       of the EXITCODEs as #defined above
  110. //-----------------------------------------------------------------------------
  111. int DPConnect_StartDirectPlayConnect( HINSTANCE hInst, BOOL bBackTrack = FALSE )
  112. {
  113.     int nExitCode;
  114.     int nStep;
  115.  
  116.     // Setup the g_DPSIHead circular linked list
  117.     ZeroMemory( &g_DPSIHead, sizeof( DPSessionInfo ) );
  118.     g_DPSIHead.pDPSINext = &g_DPSIHead;
  119.     
  120.     // If the back track flag is true, then the user has already been through
  121.     // the connect process once, and has back tracked out of the main 'game' 
  122.     // so we need start at the last dialog box
  123.     if( bBackTrack )
  124.         nStep = 1;
  125.     else
  126.         nStep = 0;
  127.  
  128.     // Show the dialog boxes to connect
  129.     while( TRUE )
  130.     {
  131.         switch( nStep )
  132.         {
  133.             case 0:
  134.                 // Display the multiplayer connect dialog box.
  135.                 nExitCode = (int)DialogBox( hInst, MAKEINTRESOURCE(IDD_MULTIPLAYER_CONNECT), 
  136.                                             NULL, (DLGPROC)DPConnect_ConnectionsDlgProc );
  137.                 break;
  138.  
  139.             case 1:
  140.                 // Display the multiplayer games dialog box.
  141.                 nExitCode = (int)DialogBox( hInst, MAKEINTRESOURCE(IDD_MULTIPLAYER_GAMES), 
  142.                                             NULL, (DLGPROC)DPConnect_SessionsDlgProc );
  143.                 break;
  144.         }
  145.  
  146.         if( nExitCode == EXITCODE_ERROR || 
  147.             nExitCode == EXITCODE_QUIT )
  148.             return nExitCode;
  149.  
  150.         if( nExitCode == EXITCODE_BACKUP )
  151.             nStep--;
  152.         else
  153.             nStep++;
  154.  
  155.         if( nExitCode == EXITCODE_LOBBYCONNECT )
  156.             return EXITCODE_LOBBYCONNECT;
  157.  
  158.         if( nStep == 2 )
  159.             break;
  160.     }
  161.  
  162.     return EXITCODE_FORWARD;
  163. }
  164.  
  165.  
  166.  
  167.  
  168. //-----------------------------------------------------------------------------
  169. // Name: DPConnect_ConnectionsDlgProc()
  170. // Desc: Handles messages for the multiplayer connect dialog
  171. //-----------------------------------------------------------------------------
  172. INT_PTR CALLBACK DPConnect_ConnectionsDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  173. {
  174.     HRESULT hr;
  175.  
  176.     switch( msg )
  177.     {
  178.         case WM_INITDIALOG:
  179.             {
  180.                 SetDlgItemText( hDlg, IDC_PLAYER_NAME_EDIT, g_strLocalPlayerName );
  181.  
  182.                 // Load and set the icon
  183. #ifdef _WIN64
  184.                 HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  185. #else
  186.                 HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  187. #endif
  188.                 HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN ) );
  189.                 SendMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  190.                 SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  191.  
  192.                 // Set the window title
  193.                 TCHAR strWindowTitle[256];
  194.                 sprintf( strWindowTitle, "%s - Multiplayer Connect", g_strAppName );
  195.                 SetWindowText( hDlg, strWindowTitle );
  196.  
  197.                 if( FAILED( hr = DPConnect_ConnectionsDlgFillListBox( hDlg ) ) )
  198.                     EndDialog( hDlg, EXITCODE_ERROR );
  199.             }
  200.             break;
  201.  
  202.         case WM_COMMAND:
  203.             switch( LOWORD(wParam) )
  204.             {
  205.                 case IDC_CONNECTION_LIST:
  206.                     if( HIWORD(wParam) != LBN_DBLCLK )
  207.                         break;
  208.                     // Fall through
  209.  
  210.                 case IDOK:
  211.                     if( FAILED( hr = DPConnect_ConnectionsDlgOnOK( hDlg ) ) )
  212.                         EndDialog( hDlg, EXITCODE_ERROR );
  213.  
  214.                     break;
  215.  
  216.                 case IDCANCEL:
  217.                     EndDialog( hDlg, EXITCODE_QUIT );
  218.                     break;
  219.  
  220.                 default:
  221.                     return FALSE; // Message not handled
  222.             }
  223.             break;
  224.         
  225.         case WM_DESTROY:
  226.             DPConnect_ConnectionsDlgCleanup( hDlg );
  227.             break;
  228.  
  229.         default:
  230.             return FALSE; // Message not handled
  231.     }
  232.  
  233.     // Message was handled
  234.     return TRUE; 
  235. }
  236.  
  237.  
  238.  
  239.  
  240. //-----------------------------------------------------------------------------
  241. // Name: DPConnect_ConnectionsDlgFillListBox()
  242. // Desc: Fills the DirectPlay connection listbox, and also adds
  243. //       a "Wait for Lobby" connection option.
  244. //-----------------------------------------------------------------------------
  245. HRESULT DPConnect_ConnectionsDlgFillListBox( HWND hDlg )
  246. {
  247.     HRESULT       hr;
  248.     HWND          hWndListBox = GetDlgItem( hDlg, IDC_CONNECTION_LIST );
  249.     LPDIRECTPLAY4 pDP = NULL;
  250.     int           nIndex;
  251.  
  252.     // Create a IDirectPlay object
  253.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_ALL, 
  254.                                        IID_IDirectPlay4A, (VOID**)&pDP ) ) )
  255.     {
  256.         if( hr == E_NOINTERFACE )
  257.         {
  258.             MessageBox( NULL, TEXT("This application requires DirectPlay 6 or later. "
  259.                         "The sample will now quit."),
  260.                         TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  261.         }
  262.  
  263.         return hr;
  264.     }
  265.  
  266.     // Enumerate all DirectPlay connections, and store them in the listbox
  267.     if( FAILED( hr = pDP->EnumConnections( &g_AppGUID, DPConnect_EnumConnectionsCallback, 
  268.                                            hWndListBox, 0 ) ) )
  269.     {
  270.         SAFE_RELEASE( pDP );
  271.         return hr;
  272.     }
  273.  
  274.     SAFE_RELEASE( pDP );
  275.     
  276.     // Add "Wait for Lobby Connection" selection in list box
  277.     SendMessage( hWndListBox, LB_ADDSTRING, 0, 
  278.                  (LPARAM)"Wait for Lobby Connection" );
  279.  
  280.     SetFocus( hWndListBox );
  281.     nIndex = (int)SendMessage( hWndListBox, LB_FINDSTRINGEXACT, -1, 
  282.                                (LPARAM)g_strPreferredProvider );
  283.     if( nIndex != LB_ERR ) 
  284.         SendMessage( hWndListBox, LB_SETCURSEL, nIndex, 0 );
  285.     else
  286.         SendMessage( hWndListBox, LB_SETCURSEL, 0, 0 );
  287.  
  288.     return S_OK;
  289. }
  290.  
  291.  
  292.  
  293.  
  294. //-----------------------------------------------------------------------------
  295. // Name: DPConnect_EnumConnectionsCallback()
  296. // Desc: Enumerates through all DirectPlay connections types, 
  297. //       and stores them in the listbox
  298. //-----------------------------------------------------------------------------
  299. BOOL FAR PASCAL DPConnect_EnumConnectionsCallback( LPCGUID   pguidSP, 
  300.                                                    VOID*     pConnection, 
  301.                                                    DWORD     dwConnectionSize, 
  302.                                                    LPCDPNAME pName, 
  303.                                                    DWORD     dwFlags, 
  304.                                                    VOID*     pvContext )
  305. {
  306.     HRESULT       hr;
  307.     LPDIRECTPLAY4 pDP = NULL;
  308.     VOID*         pConnectionBuffer = NULL;
  309.     HWND          hWndListBox = (HWND)pvContext;
  310.     LRESULT       iIndex;
  311.  
  312.     // Create a IDirectPlay object
  313.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_ALL, 
  314.                                        IID_IDirectPlay4A, (VOID**)&pDP ) ) )
  315.         return FALSE; // Error, stop enumerating
  316.     
  317.     // Test the if the connection is available by attempting to initialize 
  318.     // the connection
  319.     if( FAILED( hr = pDP->InitializeConnection( pConnection, 0 ) ) )
  320.     {
  321.         SAFE_RELEASE( pDP );
  322.         return TRUE; // Unavailable connection, keep enumerating
  323.     }
  324.  
  325.     // Don't need the IDirectPlay interface anymore, so release it
  326.     SAFE_RELEASE( pDP ); 
  327.     
  328.     // Found a good connection, so put it in the listbox
  329.     iIndex = SendMessage( hWndListBox, LB_ADDSTRING, 0, 
  330.                           (LPARAM)pName->lpszShortNameA );
  331.     if( iIndex == CB_ERR )
  332.         return FALSE; // Error, stop enumerating
  333.  
  334.     pConnectionBuffer = new BYTE[ dwConnectionSize ];
  335.     if( pConnectionBuffer == NULL )
  336.         return FALSE; // Error, stop enumerating
  337.  
  338.     // Store pointer to GUID in listbox
  339.     memcpy( pConnectionBuffer, pConnection, dwConnectionSize );
  340.     SendMessage( hWndListBox, LB_SETITEMDATA, iIndex, 
  341.                  (LPARAM)pConnectionBuffer );
  342.  
  343.     return TRUE; // Keep enumerating
  344. }
  345.  
  346.  
  347.  
  348.  
  349. //-----------------------------------------------------------------------------
  350. // Name: DPConnect_ConnectionsDlgOnOK()
  351. // Desc: Stores the player name g_strPlayerName, and in creates a IDirectPlay
  352. //       object based on the connection type the user selected. 
  353. //-----------------------------------------------------------------------------
  354. HRESULT DPConnect_ConnectionsDlgOnOK( HWND hDlg )
  355. {
  356.     VOID*   pConnection = NULL;
  357.     LRESULT iIndex;
  358.     HRESULT hr;
  359.  
  360.     GetDlgItemText( hDlg, IDC_PLAYER_NAME_EDIT, g_strLocalPlayerName, 
  361.                     MAX_PLAYER_NAME );
  362.  
  363.     if( strlen( g_strLocalPlayerName ) == 0 )
  364.     {
  365.         MessageBox( hDlg, TEXT("You must enter a valid player name."),
  366.                     TEXT("DirectPlay Sample"), MB_OK );
  367.         return S_OK;
  368.     }
  369.  
  370.     HWND hWndListBox = GetDlgItem( hDlg, IDC_CONNECTION_LIST );
  371.  
  372.     iIndex = SendMessage( hWndListBox, LB_GETCURSEL, 0, 0 );
  373.     SendMessage( hWndListBox, LB_GETTEXT, iIndex, (LPARAM)g_strPreferredProvider );
  374.  
  375.     pConnection = (VOID*) SendMessage( hWndListBox, LB_GETITEMDATA, iIndex, 0 );
  376.     if( NULL == pConnection )
  377.     {
  378.         if( FAILED( hr = DPConnect_WaitForLobbyLaunch( hDlg ) ) )
  379.         {
  380.             if( hr == DPERR_USERCANCEL )
  381.                 return S_OK;
  382.  
  383.             return hr;
  384.         }
  385.  
  386.         EndDialog( hDlg, EXITCODE_LOBBYCONNECT );
  387.         return S_OK;
  388.     }
  389.  
  390.     // Release previously selected DirectPlay object, if any.
  391.     SAFE_RELEASE( g_pDP );
  392.  
  393.     // Create the DirectPlay object
  394.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay, NULL, CLSCTX_ALL, 
  395.                                        IID_IDirectPlay4A, (VOID**)&g_pDP ) ) )
  396.         return hr;
  397.     
  398.     // Initialize the connection based on the selected connection type
  399.     if( FAILED( hr = g_pDP->InitializeConnection( pConnection, 0 ) ) )
  400.         return hr;
  401.  
  402.     EndDialog( hDlg, EXITCODE_FORWARD );
  403.  
  404.     return S_OK;
  405. }
  406.  
  407.  
  408.  
  409.  
  410. //-----------------------------------------------------------------------------
  411. // Name: DPConnect_ConnectionsDlgCleanup()
  412. // Desc: Deletes the connection buffers from the listbox
  413. //-----------------------------------------------------------------------------
  414. VOID DPConnect_ConnectionsDlgCleanup( HWND hDlg )
  415. {
  416.     VOID*   pConnectionBuffer = NULL;
  417.     DWORD   iIndex;
  418.     DWORD   dwCount;
  419.  
  420.     HWND hWndListBox = GetDlgItem( hDlg, IDC_CONNECTION_LIST );
  421.  
  422.     dwCount = (DWORD)SendMessage( hWndListBox, LB_GETCOUNT, 0, 0 );
  423.     for( iIndex = 0; iIndex < dwCount; iIndex++ )
  424.     {
  425.         pConnectionBuffer = (VOID*) SendMessage( hWndListBox, LB_GETITEMDATA, 
  426.                                                  iIndex, 0 );
  427.         SAFE_DELETE_ARRAY( pConnectionBuffer );
  428.     }
  429. }
  430.  
  431.  
  432.  
  433.  
  434. //-----------------------------------------------------------------------------
  435. // Name: DPConnect_SessionsDlgProc()
  436. // Desc: Handles messages fro the multiplayer games dialog
  437. //-----------------------------------------------------------------------------
  438. INT_PTR CALLBACK DPConnect_SessionsDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  439. {
  440.     HRESULT hr;
  441.  
  442.     switch( msg )
  443.     {
  444.         case WM_INITDIALOG:
  445.             {
  446.                 // Load and set the icon
  447. #ifdef _WIN64
  448.                 HINSTANCE hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  449. #else
  450.                 HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  451. #endif
  452.                 HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN ) );
  453.                 SendMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
  454.                 SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon
  455.  
  456.                 // Set the window title
  457.                 TCHAR strWindowTitle[256];
  458.                 sprintf( strWindowTitle, "%s - Multiplayer Games", g_strAppName );
  459.                 SetWindowText( hDlg, strWindowTitle );
  460.  
  461.                 g_bSearchingForSessions = FALSE;
  462.                 SetDlgItemText( hDlg, IDC_SEARCH_CHECK, "Start Search" );
  463.                 DPConnect_SessionsDlgInitListbox( hDlg );
  464.             }
  465.             break;
  466.  
  467.         case WM_TIMER:
  468.             if( FAILED( hr = DPConnect_SessionsDlgShowGames( hDlg ) ) )
  469.             {
  470.                 KillTimer( hDlg, 1 );
  471.                 MessageBox( hDlg, TEXT("Error enumerating DirectPlay games."),
  472.                             TEXT("DirectPlay Sample"), 
  473.                             MB_OK | MB_ICONERROR );
  474.             }
  475.             break;
  476.  
  477.         case WM_COMMAND:
  478.             switch( LOWORD(wParam) )
  479.             {
  480.                 case IDC_SEARCH_CHECK:
  481.                     g_bSearchingForSessions = !g_bSearchingForSessions;
  482.  
  483.                     if( g_bSearchingForSessions )
  484.                     {
  485.                         // Start the timer, and start the async enumeratation
  486.                         SetDlgItemText( hDlg, IDC_SEARCH_CHECK, "Searching..." );
  487.                         SetTimer( hDlg, 1, 250, NULL );
  488.                         if( FAILED( hr = DPConnect_SessionsDlgShowGames( hDlg ) ) )
  489.                         {
  490.                             KillTimer( hDlg, 1 );
  491.                             MessageBox( hDlg, TEXT("Error enumerating DirectPlay games."),
  492.                                         TEXT("DirectPlay Sample"), 
  493.                                         MB_OK | MB_ICONERROR );
  494.                         }
  495.                     }
  496.                     else
  497.                     {
  498.                         // Stop the timer, and stop the async enumeration
  499.                         KillTimer( hDlg, 1 );
  500.  
  501.                         DPSESSIONDESC2 dpsd;
  502.                         ZeroMemory( &dpsd, sizeof(dpsd) );
  503.                         dpsd.dwSize          = sizeof(dpsd);
  504.                         dpsd.guidApplication = g_AppGUID;
  505.                         hr = g_pDP->EnumSessions( &dpsd, 0, DPConnect_EnumSessionsCallback, 
  506.                                                   NULL,  DPENUMSESSIONS_STOPASYNC );
  507.                         if( hr != DPERR_GENERIC && FAILED(hr) ) 
  508.                             EndDialog( hDlg, EXITCODE_ERROR );
  509.  
  510.                         SetDlgItemText( hDlg, IDC_SEARCH_CHECK, "Start Search" );
  511.  
  512.                         DPConnect_SessionsDlgInitListbox( hDlg );
  513.                     }
  514.                     break;
  515.  
  516.                 case IDC_GAMES_LIST:
  517.                     if( HIWORD(wParam) != LBN_DBLCLK )
  518.                         break;
  519.                     // Fall through
  520.  
  521.                 case IDC_JOIN:
  522.                     if( FAILED( hr = DPConnect_SessionsDlgJoinGame( hDlg ) ) )
  523.                     {
  524.                         MessageBox( hDlg, TEXT("Unable to join game."),
  525.                                     TEXT("DirectPlay Sample"), 
  526.                                     MB_OK | MB_ICONERROR );
  527.                     }                    
  528.                     break;
  529.  
  530.                 case IDC_CREATE:
  531.                     if( FAILED( hr = DPConnect_SessionsDlgCreateGame( hDlg ) ) )
  532.                     {
  533.                         MessageBox( hDlg, TEXT("Unable to create game."),
  534.                                     TEXT("DirectPlay Sample"), 
  535.                                     MB_OK | MB_ICONERROR );
  536.                     }
  537.                     break;
  538.  
  539.                 case IDCANCEL: // The close button was press
  540.                     EndDialog( hDlg, EXITCODE_QUIT );
  541.                     break;
  542.  
  543.                 case IDC_BACK: // "Cancel" button was pressed
  544.                     EndDialog( hDlg, EXITCODE_BACKUP );
  545.                     break;
  546.  
  547.                 default:
  548.                     return FALSE; // Message not handled
  549.             }
  550.             break;
  551.         
  552.         case WM_DESTROY:
  553.             KillTimer( hDlg, 1 );                    
  554.             DPConnect_SessionsDlgCleanup();
  555.             break;
  556.  
  557.         default:
  558.             return FALSE; // Message not handled
  559.     }
  560.  
  561.     // Message was handled
  562.     return TRUE; 
  563. }
  564.  
  565.  
  566.  
  567.  
  568. //-----------------------------------------------------------------------------
  569. // Name: DPConnect_SessionsDlgInitListbox()
  570. // Desc: Initializes the listbox
  571. //-----------------------------------------------------------------------------
  572. VOID DPConnect_SessionsDlgInitListbox( HWND hDlg )
  573. {
  574.     HWND          hWndListBox = GetDlgItem( hDlg, IDC_GAMES_LIST );
  575.     LPDIRECTPLAY4 pDP = NULL;
  576.     
  577.     // Clear the contents from the list box, and 
  578.     // display "Looking for games" text in listbox
  579.     SendMessage( hWndListBox, LB_RESETCONTENT, 0, 0 );
  580.     if( g_bSearchingForSessions )
  581.     {
  582.         SendMessage( hWndListBox, LB_ADDSTRING, 0, 
  583.                      (LPARAM)"Looking for games..." );
  584.     }
  585.     else
  586.     {
  587.         SendMessage( hWndListBox, LB_ADDSTRING, 0, 
  588.                      (LPARAM)"Click Start Search to see a list of games.  "
  589.                              "Click Create to start a new game." );
  590.     }
  591.  
  592.     SendMessage( hWndListBox, LB_SETITEMDATA,  0, NULL );
  593.     SendMessage( hWndListBox, LB_SETCURSEL,    0, 0 );
  594.  
  595.     // Disable the join button until sessions are found
  596.     EnableWindow( GetDlgItem( hDlg, IDC_JOIN ), FALSE );
  597. }
  598.  
  599.  
  600.  
  601.  
  602. //-----------------------------------------------------------------------------
  603. // Name: DPConnect_SessionsDlgShowGames()
  604. // Desc: Enumerates the DirectPlay sessions, and displays them in the listbox
  605. //-----------------------------------------------------------------------------
  606. HRESULT DPConnect_SessionsDlgShowGames( HWND hDlg )
  607. {
  608.     HRESULT        hr;
  609.     HWND           hWndListBox = GetDlgItem( hDlg, IDC_GAMES_LIST );
  610.     DPSESSIONDESC2 dpsd;
  611.     DPSessionInfo* pDPSISelected = NULL;
  612.     int            nItemSelected;
  613.     GUID           guidSelectedSession;
  614.     BOOL           bFindSelectedGUID;
  615.     BOOL           bFoundSelectedGUID;
  616.  
  617.     // Try to keep the same session selected unless it goes away or 
  618.     // there is no real session currently selected
  619.     bFindSelectedGUID  = FALSE;
  620.     bFoundSelectedGUID = TRUE;
  621.  
  622.     nItemSelected = (int)SendMessage( hWndListBox, LB_GETCURSEL, 0, 0 );
  623.     if( nItemSelected != LB_ERR )
  624.     {
  625.         pDPSISelected = (DPSessionInfo*) SendMessage( hWndListBox, LB_GETITEMDATA, 
  626.                                                       nItemSelected, 0 );
  627.         if( pDPSISelected != NULL )
  628.         {
  629.             guidSelectedSession = pDPSISelected->guidSession;
  630.             bFindSelectedGUID = TRUE;
  631.         }
  632.     }
  633.     
  634.     // Remove the previous games from the linked list
  635.     DPConnect_SessionsDlgCleanup();
  636.  
  637.     // Enum sessions and let DirectPlay decide the timeout
  638.     ZeroMemory( &dpsd, sizeof(dpsd) );
  639.     dpsd.dwSize          = sizeof(dpsd);
  640.     dpsd.guidApplication = g_AppGUID;
  641.  
  642.     // Enumerate all the active DirectPlay games on the selected connection
  643.     hr = g_pDP->EnumSessions( &dpsd, 0, DPConnect_EnumSessionsCallback, NULL, 
  644.                               DPENUMSESSIONS_ALL | DPENUMSESSIONS_ASYNC );    
  645.     if( FAILED(hr) )
  646.     {
  647.         if( hr == DPERR_USERCANCEL )
  648.         {
  649.             // The user canceled the DirectPlay connection dialog, 
  650.             // so stop the search
  651.             if( g_bSearchingForSessions )
  652.             {
  653.                 CheckDlgButton( hDlg, IDC_SEARCH_CHECK, BST_UNCHECKED );
  654.                 SendMessage( hDlg, WM_COMMAND, IDC_SEARCH_CHECK, 0 );
  655.             }
  656.  
  657.             return S_OK;
  658.         }
  659.         else 
  660.         {
  661.             DPConnect_SessionsDlgInitListbox( hDlg );
  662.             if ( hr == DPERR_CONNECTING )
  663.                 return S_OK;
  664.  
  665.             return hr;
  666.         }
  667.     }
  668.  
  669.     // Tell listbox not to redraw itself since the contents are going to change
  670.     SendMessage( hWndListBox, WM_SETREDRAW, FALSE, 0 );
  671.  
  672.     // Add the enumerated sessions to the listbox
  673.     if( g_DPSIHead.pDPSINext != &g_DPSIHead )
  674.     {
  675.         // Clear the contents from the list box and enable the join button
  676.         SendMessage( hWndListBox, LB_RESETCONTENT, 0, 0 );
  677.         EnableWindow( GetDlgItem( hDlg, IDC_JOIN ), TRUE );
  678.         
  679.         DPSessionInfo* pDPSI = g_DPSIHead.pDPSINext;
  680.         while ( pDPSI != &g_DPSIHead )
  681.         {
  682.             // Add session to the list box
  683.             int nIndex = (int)SendMessage( hWndListBox, LB_ADDSTRING, 0, 
  684.                                            (LPARAM)pDPSI->szSession );
  685.             SendMessage( hWndListBox, LB_SETITEMDATA, nIndex, (LPARAM)pDPSI );
  686.  
  687.             if( bFindSelectedGUID )
  688.             {
  689.                 // Look for the session the was selected before
  690.                 if( pDPSI->guidSession == guidSelectedSession )
  691.                 {
  692.                     SendMessage( hWndListBox, LB_SETCURSEL, nIndex, 0 );
  693.                     bFoundSelectedGUID = TRUE;
  694.                 }
  695.             }
  696.  
  697.             pDPSI = pDPSI->pDPSINext;
  698.         }
  699.  
  700.         if( !bFindSelectedGUID || !bFoundSelectedGUID )
  701.             SendMessage( hWndListBox, LB_SETCURSEL, 0, 0 );
  702.     }
  703.     else
  704.     {
  705.         // There are no active session, so just reset the listbox
  706.         DPConnect_SessionsDlgInitListbox( hDlg );
  707.     }
  708.  
  709.     // Tell listbox to redraw itself now since the contents have changed
  710.     SendMessage( hWndListBox, WM_SETREDRAW, TRUE, 0 );
  711.     InvalidateRect( hWndListBox, NULL, FALSE );
  712.  
  713.     return S_OK;
  714. }
  715.  
  716.  
  717.  
  718.  
  719. //-----------------------------------------------------------------------------
  720. // Name: DPConnect_EnumSessionsCallback()
  721. // Desc: Enumerates the sessions, and stores them in the linked list, g_DPSIHead
  722. //-----------------------------------------------------------------------------
  723. BOOL FAR PASCAL DPConnect_EnumSessionsCallback( LPCDPSESSIONDESC2 pdpsd, 
  724.                                                 DWORD* pdwTimeout, 
  725.                                                 DWORD dwFlags, 
  726.                                                 VOID* pvContext )
  727. {
  728.     DPSessionInfo* pDPSINew = NULL;
  729.     
  730.     if( dwFlags & DPESC_TIMEDOUT )
  731.         return FALSE; // The enumeration has timed out, so stop the enumeration.
  732.     
  733.     // Found a good session, save it
  734.     pDPSINew = new DPSessionInfo; 
  735.     if( NULL == pDPSINew )
  736.         return FALSE;
  737.  
  738.     ZeroMemory( pDPSINew, sizeof(DPSessionInfo) );
  739.  
  740.     // Copy the information into pDPSINew
  741.     pDPSINew->guidSession = pdpsd->guidInstance;
  742.     sprintf( pDPSINew->szSession, "%s (%d/%d)", pdpsd->lpszSessionNameA, 
  743.              pdpsd->dwCurrentPlayers, pdpsd->dwMaxPlayers );
  744.  
  745.     // Add pDPSINew to the circular linked list, g_pDPSIFirst
  746.     pDPSINew->pDPSINext = g_DPSIHead.pDPSINext;
  747.     g_DPSIHead.pDPSINext = pDPSINew;
  748.     
  749.     return TRUE;
  750. }
  751.  
  752.  
  753.  
  754.  
  755. //-----------------------------------------------------------------------------
  756. // Name: DPConnect_SessionsDlgJoinGame()
  757. // Desc: Joins the selected DirectPlay session
  758. //-----------------------------------------------------------------------------
  759. HRESULT DPConnect_SessionsDlgJoinGame( HWND hDlg )
  760. {
  761.     DPSESSIONDESC2 dpsd;
  762.     DPNAME         dpname;
  763.     HRESULT        hr;
  764.     HWND           hWndListBox = GetDlgItem( hDlg, IDC_GAMES_LIST );
  765.     DPSessionInfo* pDPSISelected = NULL;
  766.     int            nItemSelected;
  767.  
  768.     nItemSelected = (int)SendMessage( hWndListBox, LB_GETCURSEL, 0, 0 );
  769.     
  770.     // Add status text in list box
  771.     pDPSISelected = (DPSessionInfo*) SendMessage( hWndListBox, LB_GETITEMDATA, 
  772.                                                   nItemSelected, 0 );
  773.  
  774.     if( NULL == pDPSISelected )
  775.     {
  776.         MessageBox( hDlg, TEXT("There are no games to join."),
  777.                     TEXT("DirectPlay Sample"), MB_OK );
  778.         return S_OK;
  779.     }
  780.  
  781.     // Setup the DPSESSIONDESC2, and get the session guid from 
  782.     // the selected listbox item
  783.     ZeroMemory( &dpsd, sizeof(dpsd) );
  784.     dpsd.dwSize          = sizeof(dpsd);
  785.     dpsd.guidInstance    = pDPSISelected->guidSession;
  786.     dpsd.guidApplication = g_AppGUID;
  787.  
  788.     // Join the session
  789.     g_bHostPlayer = FALSE;
  790.     if( FAILED( hr = g_pDP->Open( &dpsd, DPOPEN_JOIN ) ) )
  791.         return hr;
  792.  
  793.     // Check for Async message support
  794.     // The caps we are checking do not differ for guaranteed msg
  795.     DPCAPS  dpcaps;
  796.     ZeroMemory( &dpcaps, sizeof(DPCAPS) );
  797.     dpcaps.dwSize = sizeof(DPCAPS);
  798.     g_pDP->GetCaps( &dpcaps, 0 );
  799.  
  800.     // Determine if Aync messages are supported.
  801.     g_bAsyncSupported = (dpcaps.dwFlags & DPCAPS_ASYNCSUPPORTED) != 0;
  802.  
  803.     // Create player based on g_strLocalPlayerName.  
  804.     // Store the player's DPID in g_LocalPlayerDPID.
  805.     // Also all DirectPlay messages for this player will signal g_hDPMessageEvent
  806.     ZeroMemory( &dpname, sizeof(DPNAME) );
  807.     dpname.dwSize         = sizeof(DPNAME);
  808.     dpname.lpszShortNameA = g_strLocalPlayerName;
  809.     
  810.     if( FAILED( hr = g_pDP->CreatePlayer( &g_LocalPlayerDPID, &dpname, 
  811.                                           g_hDPMessageEvent, NULL, 0, 0 ) ) )
  812.         return hr;
  813.  
  814.     // DirectPlay connect successful, so end dialog
  815.     EndDialog( hDlg, EXITCODE_FORWARD );
  816.  
  817.     return S_OK;
  818. }
  819.  
  820.  
  821.  
  822.  
  823. //-----------------------------------------------------------------------------
  824. // Name: DPConnect_SessionsDlgCreateGame()
  825. // Desc: Asks the user the session name, and creates a new DirectPlay session
  826. //-----------------------------------------------------------------------------
  827. HRESULT DPConnect_SessionsDlgCreateGame( HWND hDlg )
  828. {
  829.     DPSESSIONDESC2 dpsd;
  830.     DPNAME         dpname;
  831.     HRESULT        hr;
  832.     int            nResult; 
  833.     HINSTANCE      hInst;
  834.  
  835. #ifdef _WIN64
  836.     hInst = (HINSTANCE) GetWindowLongPtr( hDlg, GWLP_HINSTANCE );
  837. #else
  838.     hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
  839. #endif
  840.  
  841.     // Display a modal multiplayer connect dialog box.
  842.     EnableWindow( hDlg, FALSE ); 
  843.     nResult = (int)DialogBox( hInst, MAKEINTRESOURCE(IDD_MULTIPLAYER_CREATE), 
  844.                          hDlg, (DLGPROC)DPConnect_CreateSessionDlgProc );
  845.     EnableWindow( hDlg, TRUE ); 
  846.  
  847.     if( nResult == IDCANCEL )
  848.         return S_OK;
  849.  
  850.     // Setup the DPSESSIONDESC2 based on g_AppGUID, and g_strSessionName.
  851.     // The DPSESSION_KEEPALIVE flag keeps the session alive if players abnormally exit
  852.     ZeroMemory( &dpsd, sizeof(dpsd) );
  853.     dpsd.dwSize           = sizeof(dpsd);
  854.     dpsd.guidApplication  = g_AppGUID;
  855.     dpsd.lpszSessionNameA = g_strSessionName;
  856.     dpsd.dwMaxPlayers     = 10;
  857.     dpsd.dwFlags          = DPSESSION_KEEPALIVE | DPSESSION_MIGRATEHOST;
  858.     if( g_bUseProtocol )
  859.         dpsd.dwFlags |= DPSESSION_DIRECTPLAYPROTOCOL;
  860.  
  861.     // Create a new session
  862.     g_bHostPlayer = TRUE;
  863.     if( FAILED( hr = g_pDP->Open( &dpsd, DPOPEN_CREATE ) ) )
  864.         return hr;
  865.  
  866.     // Check for Async message support
  867.     // The caps we are checking do not differ for guaranteed msg
  868.     DPCAPS  dpcaps;
  869.     ZeroMemory( &dpcaps, sizeof(DPCAPS) );
  870.     dpcaps.dwSize = sizeof(DPCAPS);
  871.     g_pDP->GetCaps( &dpcaps, 0 );
  872.  
  873.     // Determine if Aync messages are supported.
  874.     g_bAsyncSupported = (dpcaps.dwFlags & DPCAPS_ASYNCSUPPORTED) != 0;
  875.  
  876.     // Create player based on g_strLocalPlayerName.  
  877.     // Store the player's DPID in g_LocalPlayerDPID.
  878.     // Also all DirectPlay messages for this player will signal g_hDPMessageEvent
  879.     ZeroMemory( &dpname, sizeof(DPNAME) );
  880.     dpname.dwSize         = sizeof(DPNAME);
  881.     dpname.lpszShortNameA = g_strLocalPlayerName;
  882.  
  883.     if( FAILED( hr = g_pDP->CreatePlayer( &g_LocalPlayerDPID, &dpname, 
  884.                                           g_hDPMessageEvent, NULL, 0, 
  885.                                           DPPLAYER_SERVERPLAYER ) ) )
  886.         return hr;
  887.  
  888.     // DirectPlay connect successful, so end dialog
  889.     EndDialog( hDlg, EXITCODE_FORWARD );
  890.  
  891.     return S_OK;
  892. }
  893.  
  894.  
  895.  
  896.  
  897. //-----------------------------------------------------------------------------
  898. // Name: DPConnect_CreateSessionDlgProc()
  899. // Desc: Handles messages fro the multiplayer create game dialog
  900. //-----------------------------------------------------------------------------
  901. INT_PTR CALLBACK DPConnect_CreateSessionDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  902. {
  903.     DWORD dwNameLength;
  904.  
  905.     switch( msg ) 
  906.     {
  907.         case WM_INITDIALOG:
  908.             SetDlgItemText( hDlg, IDC_EDIT_SESSION_NAME, g_strSessionName );
  909.             return TRUE;
  910.  
  911.         case WM_COMMAND:
  912.             switch( LOWORD(wParam) )
  913.             {
  914.                 case IDOK:
  915.                     dwNameLength = GetDlgItemText( hDlg, IDC_EDIT_SESSION_NAME, 
  916.                                                    g_strSessionName, 
  917.                                                    MAX_SESSION_NAME );
  918.                     if( dwNameLength == 0 )
  919.                         return TRUE; // Don't accept blank session names
  920.  
  921.                     g_bUseProtocol = TRUE;
  922.  
  923.                     EndDialog( hDlg, IDOK );
  924.                     return TRUE;
  925.  
  926.                 case IDCANCEL:
  927.                     EndDialog( hDlg, IDCANCEL );
  928.                     return TRUE;
  929.             }
  930.             break;
  931.     }
  932.  
  933.     return FALSE; // Didn't handle message
  934. }
  935.  
  936.  
  937.  
  938.  
  939. //-----------------------------------------------------------------------------
  940. // Name: DPConnect_SessionsDlgCleanup()
  941. // Desc: Deletes the linked list, g_DPSIHead
  942. //-----------------------------------------------------------------------------
  943. VOID DPConnect_SessionsDlgCleanup()
  944. {
  945.     DPSessionInfo* pDPSI = g_DPSIHead.pDPSINext;
  946.     DPSessionInfo* pDPSIDelete;
  947.  
  948.     while ( pDPSI != &g_DPSIHead )
  949.     {
  950.         pDPSIDelete = pDPSI;       
  951.         pDPSI = pDPSI->pDPSINext;
  952.  
  953.         SAFE_DELETE( pDPSIDelete );
  954.     }
  955.  
  956.     // Re-link the g_DPSIHead circular linked list
  957.     g_DPSIHead.pDPSINext = &g_DPSIHead;
  958. }
  959.  
  960.  
  961.  
  962.  
  963. //-----------------------------------------------------------------------------
  964. // Name: DPConnect_WaitForLobbyLaunch()
  965. // Desc: Wait for the a lobby connection and connect when found
  966. //-----------------------------------------------------------------------------
  967. HRESULT DPConnect_WaitForLobbyLaunch( HWND hParentDlg )
  968. {
  969.     HRESULT hr;
  970.     BOOL    bLaunchedByLobby;
  971.  
  972.     // Create a new lobby object
  973.     SAFE_RELEASE( g_pDPLobby );
  974.  
  975.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayLobby, NULL,
  976.                                        CLSCTX_INPROC_SERVER, IID_IDirectPlayLobby3A,
  977.                                        (VOID**)&g_pDPLobby ) ) )
  978.         return hr;
  979.  
  980.     // Put the application into wait mode
  981.     if( FAILED( hr = g_pDPLobby->WaitForConnectionSettings( 0 ) ) )
  982.         return hr;
  983.  
  984.     // Use the IDD_LOBBY_WAIT_STATUS dialog to check for a connection message
  985.     g_bWaitForConnectionSettings = TRUE;
  986.  
  987.     EnableWindow( hParentDlg, FALSE );
  988.  
  989.     // Display a dialog box and wait for the connection settings
  990.     DialogBoxParam( NULL, MAKEINTRESOURCE( IDD_LOBBY_WAIT_STATUS ), hParentDlg,
  991.                     (DLGPROC)DPConnect_LobbyWaitDlgProc, (LPARAM)&hr );
  992.    
  993.     EnableWindow( hParentDlg, TRUE );
  994.  
  995.     if( FAILED(hr) )
  996.     {
  997.         g_pDPLobby->WaitForConnectionSettings( DPLWAIT_CANCEL );
  998.         SAFE_RELEASE( g_pDPLobby );
  999.  
  1000.         return hr;
  1001.     }
  1002.  
  1003.     // The lobby server has launched the game, so check for a lobby
  1004.     // launch to continue on to connect to the session and create the player
  1005.     if( FAILED( hr = DPConnect_CheckForLobbyLaunch( &bLaunchedByLobby ) ) )
  1006.         return hr; // This may be DPERR_USERCANCEL if the user canceled the dialog
  1007.  
  1008.     return S_OK;
  1009. }
  1010.  
  1011.  
  1012.  
  1013.  
  1014. //-----------------------------------------------------------------------------
  1015. // Name: DPConnect_CheckForLobbyLaunch()
  1016. // Desc: Determines if we were launched by a lobby. If so, gets the connection
  1017. //       settings and creates our player using the information from the lobby
  1018. //-----------------------------------------------------------------------------
  1019. HRESULT DPConnect_CheckForLobbyLaunch( BOOL* pbLaunchedByLobby )
  1020. {
  1021.     HRESULT hr;
  1022.     DWORD   dwSize;
  1023.  
  1024.     if( NULL == pbLaunchedByLobby ) 
  1025.         return E_FAIL;
  1026.  
  1027.     // Create a new lobby object
  1028.     SAFE_RELEASE( g_pDPLobby );
  1029.  
  1030.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlayLobby, NULL,
  1031.                                        CLSCTX_INPROC_SERVER, IID_IDirectPlayLobby3A,
  1032.                                        (VOID**)&g_pDPLobby ) ) )
  1033.     {
  1034.         if( hr == E_NOINTERFACE )
  1035.         {
  1036.             MessageBox( NULL, TEXT("This application requires DirectPlay 6 or later. "
  1037.                         "The sample will now quit."),
  1038.                         TEXT("DirectPlay Sample"), MB_OK | MB_ICONERROR );
  1039.         }
  1040.  
  1041.         return hr;
  1042.     }
  1043.  
  1044.     // Get connection settings from the lobby (into g_pdplConnection)
  1045.     hr = g_pDPLobby->GetConnectionSettings( 0, NULL, &dwSize );
  1046.     if( FAILED(hr) && (DPERR_BUFFERTOOSMALL != hr) )
  1047.     {
  1048.         if( DPERR_NOTLOBBIED == hr )
  1049.         {
  1050.             *pbLaunchedByLobby = FALSE;
  1051.  
  1052.             // Cleanup since we were not launched from the lobby
  1053.             SAFE_DELETE_ARRAY( g_pDPLConnection );
  1054.             SAFE_RELEASE( g_pDPLobby );
  1055.  
  1056.             return S_OK;
  1057.         }
  1058.  
  1059.         return hr; 
  1060.     }
  1061.  
  1062.     // Allocate memory for the connection
  1063.     SAFE_DELETE_ARRAY( g_pDPLConnection );
  1064.     g_pDPLConnection = (DPLCONNECTION*)new BYTE[ dwSize ];
  1065.  
  1066.     // Get the connection settings
  1067.     if( FAILED( hr = g_pDPLobby->GetConnectionSettings( 0, g_pDPLConnection, 
  1068.                                                         &dwSize ) ) )
  1069.         return hr;
  1070.  
  1071.     *pbLaunchedByLobby = TRUE;
  1072.  
  1073.     if( FAILED( hr = DPConnect_DoLobbyLaunch() ) )
  1074.     {
  1075.         // Cleanup 
  1076.         SAFE_DELETE_ARRAY( g_pDPLConnection );
  1077.         SAFE_RELEASE( g_pDPLobby );
  1078.  
  1079.         return hr; // This may be DPERR_USERCANCEL if the user canceled the dialog
  1080.     }
  1081.  
  1082.     return S_OK;
  1083. }
  1084.  
  1085.  
  1086.  
  1087.  
  1088. //-----------------------------------------------------------------------------
  1089. // Name: DPConnect_DoLobbyLaunch()
  1090. // Desc: The app was launched by the lobby server, so connect to the session
  1091. //       and create the player
  1092. //-----------------------------------------------------------------------------
  1093. HRESULT DPConnect_DoLobbyLaunch()
  1094. {
  1095.     HRESULT hr;
  1096.  
  1097.     // Detrimine if this is the host player 
  1098.     g_bHostPlayer = ( (g_pDPLConnection->dwFlags & DPLCONNECTION_CREATESESSION) != 0 );
  1099.  
  1100.     // Set our session flags
  1101.     g_pDPLConnection->lpSessionDesc->dwFlags = DPSESSION_KEEPALIVE | 
  1102.                                                DPSESSION_MIGRATEHOST;
  1103.  
  1104.     // Let lobby know our connection flags
  1105.     if( FAILED( hr = g_pDPLobby->SetConnectionSettings( 0, 0, g_pDPLConnection ) ) )
  1106.         return hr;
  1107.  
  1108.     // If we're hosting, just call ConnectEx syncronously.  Otherwise, display
  1109.     // the connecting dialog and do the connect asynchronously.
  1110.     if( g_bHostPlayer )
  1111.     {
  1112.         // Connect to the lobby syncronously
  1113.         if( FAILED( hr = g_pDPLobby->ConnectEx( 0, IID_IDirectPlay4A, 
  1114.                                                 (VOID**)&g_pDP, NULL ) ) )
  1115.             return hr;
  1116.     }
  1117.     else
  1118.     {
  1119.         // Use the IDD_LOBBY_WAIT_STATUS dialog to attempt to connect to 
  1120.         // the new session
  1121.         g_bWaitForConnectionSettings = FALSE;
  1122.  
  1123.         // Connect to the lobby asyncronously
  1124.         DialogBoxParam( NULL, MAKEINTRESOURCE( IDD_LOBBY_WAIT_STATUS ), NULL,
  1125.                         (DLGPROC)DPConnect_LobbyWaitDlgProc, (LPARAM)&hr );
  1126.         if( FAILED(hr) )
  1127.             return hr; // This may be DPERR_USERCANCEL if the user canceled the dialog
  1128.     }
  1129.  
  1130.     strcpy( g_strLocalPlayerName, g_pDPLConnection->lpPlayerName->lpszShortNameA );
  1131.  
  1132.     // Create our player
  1133.     DPNAME dpname;
  1134.     ZeroMemory( &dpname, sizeof(DPNAME) );
  1135.     dpname.dwSize         = sizeof(DPNAME);
  1136.     dpname.lpszShortNameA = g_strLocalPlayerName;
  1137.  
  1138.     if( FAILED( hr = g_pDP->CreatePlayer( &g_LocalPlayerDPID, &dpname, 
  1139.                                           NULL, NULL, 0, 0 ) ) )
  1140.         return hr;
  1141.  
  1142.     // Successfully lobby launch, note that we don't release the lobby object
  1143.     return S_OK;
  1144. }
  1145.  
  1146.  
  1147.  
  1148.  
  1149. //-----------------------------------------------------------------------------
  1150. // Name: DPConnect_LobbyWaitDlgProc()
  1151. // Desc: Handles dialog messages.  This dialog starts a timer that attempts to
  1152. //       either receive a lobby connection settings message or 
  1153. //       connect to new session via the lobby connection depending on the 
  1154. //       g_bWaitForConnectionSettings flag.
  1155. //-----------------------------------------------------------------------------
  1156. INT_PTR CALLBACK DPConnect_LobbyWaitDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
  1157. {
  1158.     static HRESULT* phr = NULL;
  1159.  
  1160.     switch( msg )
  1161.     {
  1162.         case WM_INITDIALOG:
  1163.             // Save the HRESULT pointer
  1164.             phr = (HRESULT*)lParam;           
  1165.  
  1166.             if( g_bWaitForConnectionSettings )
  1167.                 SetDlgItemText( hDlg, IDC_WAIT_TEXT, TEXT("Waiting for connection...") );
  1168.             else
  1169.                 SetDlgItemText( hDlg, IDC_WAIT_TEXT, TEXT("Finding Game...") );
  1170.  
  1171.             // Create a timer.  The dialog will attempt to connect at every WM_TIMER
  1172.             SetTimer( hDlg, 0, 250, NULL );
  1173.             break;
  1174.  
  1175.         case WM_DESTROY:
  1176.             KillTimer( hDlg, 0 );
  1177.             break;
  1178.  
  1179.         case WM_TIMER:
  1180.             // Attempt to connect to the game
  1181.             if( g_bWaitForConnectionSettings )
  1182.             {
  1183.                 *phr = DPConnect_GetLobbyConnectionSettingsMessage();
  1184.                 if( *phr == S_OK )
  1185.                     EndDialog( hDlg, 0 );
  1186.             }
  1187.             else
  1188.             {
  1189.                 *phr = g_pDPLobby->ConnectEx( DPCONNECT_RETURNSTATUS, IID_IDirectPlay4A, 
  1190.                                               (VOID**)&g_pDP, NULL );
  1191.                 if( *phr == DPERR_CONNECTING )
  1192.                     break; // Try again on the next WM_TIMER message
  1193.  
  1194.                 EndDialog( hDlg, 0 );
  1195.             }
  1196.  
  1197.             break;
  1198.         
  1199.         case WM_COMMAND:
  1200.             switch( LOWORD(wParam) )
  1201.             {
  1202.                 case IDC_LOBBYCONNECTCANCEL:
  1203.                 case IDCANCEL:
  1204.                     // the async Connect will be stopped when the
  1205.                     // IDirectPlayLobby3 interface is released.
  1206.                     
  1207.                     // Set the HRESULT to user cancel and close the dialog
  1208.                     *phr = DPERR_USERCANCEL;
  1209.                     EndDialog( hDlg, 0 );
  1210.                     break;
  1211.  
  1212.                 default:
  1213.                     return FALSE; // Message not handled
  1214.             }
  1215.             break;
  1216.  
  1217.         default:
  1218.             return FALSE; // Message not handled
  1219.     }
  1220.  
  1221.     return TRUE; // Message handled
  1222. }
  1223.  
  1224.  
  1225.  
  1226.  
  1227. //-----------------------------------------------------------------------------
  1228. // Name: DPConnect_GetLobbyConnectionSettingsMessage()
  1229. // Desc: Attepts to get a lobby connection settings message.  If it does 
  1230. //       it returns S_OK otherwise it returns S_FALSE 
  1231. //-----------------------------------------------------------------------------
  1232. HRESULT DPConnect_GetLobbyConnectionSettingsMessage()
  1233. {
  1234.     HRESULT hr = NOERROR;
  1235.     LPVOID  pvMsgBuffer = NULL;
  1236.     DWORD   dwMsgBufferSize = 0;
  1237.     DWORD   dwMsgFlags;
  1238.  
  1239.     while( TRUE )
  1240.     {
  1241.         hr = g_pDPLobby->ReceiveLobbyMessage( 0, 0, &dwMsgFlags,
  1242.                                               pvMsgBuffer, &dwMsgBufferSize );
  1243.         if( hr == DPERR_BUFFERTOOSMALL ) 
  1244.         {
  1245.             // The current buffer was too small, 
  1246.             // so reallocate it and try again
  1247.             SAFE_DELETE_ARRAY( pvMsgBuffer );
  1248.  
  1249.             pvMsgBuffer = new BYTE[ dwMsgBufferSize ];
  1250.             if( pvMsgBuffer == NULL )
  1251.                 return E_OUTOFMEMORY;
  1252.  
  1253.             continue; // Now that the buffer is bigger, try again
  1254.         }
  1255.  
  1256.         if( DPERR_NOMESSAGES == hr )
  1257.             break;
  1258.  
  1259.         if( FAILED(hr) )
  1260.             break;
  1261.  
  1262.         // Found a messages, check to see if its a CONNECTIONSETTINGS message
  1263.         if( dwMsgFlags & DPLMSG_SYSTEM )
  1264.         {
  1265.             // If it is found then stop looking for it
  1266.             if( ( (DPLMSG_GENERIC*)pvMsgBuffer)->dwType == DPLSYS_NEWCONNECTIONSETTINGS )
  1267.                 break;
  1268.         }
  1269.     }
  1270.  
  1271.     // Cleanup buffer
  1272.     SAFE_DELETE_ARRAY( pvMsgBuffer );
  1273.  
  1274.     // Return S_FALSE if there we no connection settings messages
  1275.     if( DPERR_NOMESSAGES == hr )
  1276.         return S_FALSE;
  1277.  
  1278.     // If the message was recieved the hr should be S_OK
  1279.     return hr; 
  1280. }
  1281.  
  1282.  
  1283.